package site.luojie.core.factory;

import site.luojie.core.bean.Bean;
import site.luojie.core.bean.BeanProperty;
import site.luojie.core.io.Resources;
import site.luojie.core.parse.XMLBeanParse;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 应用上下文
 * @Author jie.luo
 * @Create: 2020-05-05 22:52
 **/
public class ClasspathXmlApplicationContext extends AbstractApplicationContext {

    public ClasspathXmlApplicationContext(String resource) throws Exception {

        // 解析配置文件
        parseXml(resource);

        createBean();
    }

    /**
     * 解析xml
     *
     * @param resource 配置文件
     * @throws Exception
     */
    public void parseXml(String resource) throws Exception {
        // 加载配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        // 获取所有 bean
        beans = new XMLBeanParse().parse(resourceAsStream);
    }

    /**
     * 构建 bean
     */
    public void createBean() throws Exception {

        // 所有Bean 下的 property
        List<BeanProperty> beanProperties = new ArrayList<>();

        for (Bean bean : beans) {
            Object o = Class.forName(bean.getClassName()).newInstance();
            beanMap.put(bean.getId(), o);

            beanProperties.addAll(bean.getBeanProperties());
        }

        if (beanProperties.size() > 0) {
            for (BeanProperty beanProperty : beanProperties) {
                String parentId = beanProperty.getParentId();
                String ref = beanProperty.getRef();

                Object refObject = beanMap.get(ref);
                Object parentObject = beanMap.get(parentId);

                for (Method method : parentObject.getClass().getMethods()) {

                    if (method.getName().equals("set" + beanProperty.getTitleCaseName())) {
                        method.invoke(parentObject, refObject);
                    }
                }
                beanMap.put(parentId, parentObject);
            }
        }
    }

    @Override
    public Object getContextBean(String name) {
        return beanMap.get(name);
    }

    @Override
    public <T> T getContextBean(Class<T> requiredType) {
        return null;
    }


}
